//
//  YTClient.m
//  tesDemo02
//
//  Created by 拓客营 on 2022/3/23.
//

#import "YTClient.h"
#import "LoginViewController.h"

@implementation YTUser

- (void)encodeWithCoder:(NSCoder *)aCoder {
    unsigned int count = 0; //成员变量的个数
    Ivar *ivarList = class_copyIvarList(YTUser.class, &count);
    for (int i = 0; i < count; i++) {
        Ivar ivar = ivarList[i];
        NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
        [aCoder encodeObject:[self valueForKey:key] forKey:key];
    }
    free(ivarList);  //但凡在C语言里面 看到New Creat Copy 都需要释放
}

- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder {
    if (self == [super init]) {
        unsigned int count = 0; //成员变量的个数
        Ivar *ivarList = class_copyIvarList(YTUser.class, &count);
        for (int i = 0; i < count; i++) {
            Ivar ivar = ivarList[i];
            NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
            [self setValue:[aDecoder decodeObjectForKey:key] forKey:key];
        }
        free(ivarList);  //但凡在C语言里面 看到New Creat Copy 都需要释放
    }
    return self;
}

- (id)copyWithZone:(NSZone *)zone {
    YTUser *user = [[YTUser allocWithZone:zone] init];
    
    unsigned int count = 0; //成员变量的个数
    Ivar *ivarList = class_copyIvarList(YTUser.class, &count);
    for (int i = 0; i < count; i++) {
        Ivar ivar = ivarList[i];
        NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
        [user setValue:[self valueForKey:key.copy] forKey:key];
    }
    free(ivarList);

    return user;
}

- (NSString *)description {
    
    NSString *content = @"";
    unsigned int count = 0; //成员变量的个数
    Ivar *ivarList = class_copyIvarList(YTUser.class, &count);
    for (int i = 0; i < count; i++) {
        Ivar ivar = ivarList[i];
        NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
        
        content = [content stringByAppendingFormat:@"%@:%@\n", key, [self valueForKey:key.copy]];
    }
    free(ivarList);
    return content;
}

+(NSDictionary *)mj_replacedKeyFromPropertyName {
    return @{@"userId":@"id"};
}

@end

@interface YTClient()

@property (nonatomic, copy, readonly) NSString *storagePath;
@property (nonatomic, strong) YYKVStorage *storage;

@property(nonatomic,copy)dispatch_source_t timer;

@end

@implementation YTClient

- (instancetype)initWithPath:(NSString *)path {
    self = [super init];
    if (self) {
        NSAssert(path, @"the path is not directly");
        _storage = [[YYKVStorage alloc] initWithPath:path type:YYKVStorageTypeSQLite];
#if DEBUG
        ///< 开发环境开启调试
        _storage.errorLogsEnabled = YES;
#endif
    }
    return self;
}

+ (YTClient *)shared {
    static YTClient *_client = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSString *defaultPath = [UIApplication sharedApplication].documentsPath;
        defaultPath = [defaultPath stringByAppendingPathComponent:@"YTClient"];
        _client = [[YTClient alloc] initWithPath:defaultPath];
    });
    return _client;
}

- (BOOL)updateUser:(YTUser *)user {
    [APIManager manager].token = user.token;
    YYKVStorageItem *item = [[YYKVStorageItem alloc] init];
    item.key = @"userStorageItemKey";
    item.value = [self dataWithObject:user archiveKey:@"userArchiveKey"];
    return [self.storage saveItem:item];
}

- (BOOL)updateVersion {
    YYKVStorageItem *item = [[YYKVStorageItem alloc] init];
    item.key = @"AppVersionStorageItemKey";
    item.value = [UIApplication.sharedApplication.appVersion dataUsingEncoding:NSUTF8StringEncoding];
    return [self.storage saveItem:item];
}

- (YTUser *)userWithDict:(NSDictionary *)dict {
    return [YTUser modelWithDictionary:dict];
}

- (void)loginInWithData:(id)responseObject {
    
    YTUser *user = [YTUser mj_objectWithKeyValues:responseObject[@"data"]];
    NSString *token = FormatString(@"%@",responseObject[@"data"][@"access_token"]);
    user.token = token;
    [self updateUser:user];
    [APIManager manager].token = token;
    [self heartbeatStrar];
}

- (BOOL)logout {
    
    [self heartbeatEnd];
    [APIManager manager].token = @"";
    BOOL isSuccess = [self.storage removeAllItems];
    [[NSNotificationCenter defaultCenter] postNotificationName:NotifiName_LoginStateChange object:@{@"loginIn":@"0"}];
    return isSuccess;
}

- (void)logoutWithCompletionHandler:(void (^)(BOOL, NSError * _Nullable))completionHandler {
    [self.storage removeAllItemsWithProgressBlock:^(int removedCount, int totalCount) {
        
//        if (DEBUG) {
//            NSLog(@"delete progress:%.2lf", removedCount / (float)totalCount);
//        }
        
    } endBlock:^(BOOL error) {
       
        if (completionHandler) {
            completionHandler(error, nil);
        }
        
    }];
}

- (id)copyWithZone:(NSZone *)zone {
    return self;
}

- (id)mutableCopyWithZone:(NSZone *)zone {
    return self;
}

- (NSData *)dataWithObject:(id<NSCoding>)object archiveKey:(NSString *)archivekey{
    NSMutableData *data = [[NSMutableData alloc] init];
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
    [archiver encodeObject:object forKey:archivekey];
    [archiver finishEncoding];
    return data;
}

- (id<NSCoding>)objectFromStorageWithStorageKey:(NSString *)storageKey archiveKey:(NSString *)archivekey{
    
    YYKVStorageItem *item = [self.storage getItemForKey:storageKey];
    if (!item) return nil;
    NSKeyedUnarchiver *unchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:item.value];
    
    if (![unchiver containsValueForKey:archivekey]) {
        return nil;
    }
    id<NSCoding> obj = [unchiver decodeObjectForKey:archivekey];
    return obj;
}

- (void)presentLoginControllerFrom:(UIViewController *)controller showClose:(BOOL)showClose{
    
    if (!self.isShowingLogin) {
        LoginViewController *vc = [[LoginViewController alloc]initWithShowClose:YES];
        BaseNavigationController *nav = [[BaseNavigationController alloc]initWithRootViewController:vc];
        [controller yt_presentViewController:nav animated:YES completion:nil];
    }
    
}

- (BOOL)isMember {
    // 先判断是否在过期时间内
    
    return self.user.level != 0;
}

- (BOOL)isLogin {
    return self.user != nil;
}

- (YTUser *)user {
    return (YTUser *)[self objectFromStorageWithStorageKey:@"userStorageItemKey" archiveKey:@"userArchiveKey"];
}

//- (BKJPushSetting *)JPushSetting {
//    return (BKJPushSetting *)[self objectFromStorageWithStorageKey:@"JPushStorageItemKey" archiveKey:@"JPushArchiveKey"];
//}

- (NSString *)storagePath {
    NSString *defaultPath = [UIApplication sharedApplication].documentsPath;
    defaultPath = [defaultPath stringByAppendingPathComponent:@"YTClient"];
    return defaultPath;
}

#pragma mark - 心跳相关

// 登录后的心跳接口
-(void)heartbeatStrar {
    WeakSelf;
    
    [self heartbeatEnd];
    
    dispatch_source_set_timer(self.timer, dispatch_walltime(NULL, 0), 30.0 * NSEC_PER_SEC, 0);
    dispatch_source_set_event_handler(_timer, ^{
        [weakSelf sendheartBeatNetwork];
    });
    dispatch_resume(_timer);
}

-(void)heartbeatEnd {
    if (_timer) {
        dispatch_source_cancel(_timer);
        _timer = nil;
    }
}

-(void)sendheartBeatNetwork {
    
    WeakSelf;
    [[APIManager manager] Get:URL_Heartbeat parameters:nil success:^(id  _Nonnull responseObject) {
        if (NET_RESULT_CODE == 200) {
            
        }else if (NET_RESULT_CODE == 401){
            [[YTClient shared] logout];
            [weakSelf heartbeatEnd];
            
            [MBProgressHUD showMessage:@"您已在其他地方登录"];
        }else {
            NET_SHOW_MSG;
        }
    } failure:^(NSError * _Nonnull error) {
        NET_SHOW_ERROR;
    }];
}

-(dispatch_source_t)timer {
    if (!_timer) {
        _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
    }
    return _timer;
}

@end
